/**
 * @file TextWindowList.h
 * @brief Routines for manipulating lists of text windows
 * @author Ajit Warrier @date 28 Oct 2005
 * $Id: TextWindowList.c 10 2007-06-28 20:08:57Z mfms $
 */

/*
 *  Copyright (C) 2001, 2005  Ajit Warrier, Matthias Stallmann.
 *  Contact: matt_stallmann@ncsu.edu
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program (file COPYING.txt); if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 *  USA.
 */

#include "TextWindowList.h"

struct ListNode {
  Window my_window;
  char * my_string;
  struct ListNode * my_next_node;
};

static TWIN listHead = NULL; // pointer to start of linked list

TWIN TWL_add(Window win){
  TWIN new_node = malloc(sizeof(struct ListNode));

  new_node->my_window = win;
  new_node->my_string = NULL;
#if defined(PUT_AT_LIST_END)
  /* this more complex code is only needed if the order of list items matters
     */
  new_node->my_next_node = NULL;

  TWIN iter = listHead;
  if(iter == NULL) { /* if list was empty */
    listHead = new_node;
  }
  else {
    while(iter->my_next_node != NULL) /* go to end of list */
      iter = iter->my_next_node;
    /* here iter points to the last node of the list */
    iter->my_next_node = new_node;
  }
#else
  new_node->my_next_node = listHead;
  listHead = new_node;
#endif
  return new_node;
}

void TWL_remove(TWIN win){
  TWIN prev = NULL;
  TWIN next = listHead;

  while(next != NULL && next != win){
    /* INV: prev == NULL || prev->my_next_node == next */
    prev = next;
    next = next->my_next_node;
  }
  
  if(next != NULL){ /* if the element exists in list */
    if(next->my_string != NULL) {
      free(next->my_string);
    }
    if(next == listHead){/* need to delete first element */
      TWIN soon_to_die = listHead;
      listHead = listHead->my_next_node;
      free(soon_to_die);
    } else{ /* need to delete element in the middle */
      TWIN soon_to_die = next;
      prev->my_next_node = next->my_next_node;
      free(soon_to_die);
    }
  }
}

void TWL_change(TWIN win, const char *msg){
  if(win != NULL && msg != NULL){
    if(win->my_string != NULL) /* need to free previous string */
      free(win->my_string);
    win->my_string = malloc(1 + strlen(msg));
    strcpy(win->my_string, msg);
  }
}

Window TWL_window(TWIN win){
  if(win)
    return win->my_window;
  return main_canvas;
}

const char* TWL_message(TWIN win){
  if(win)
    return win->my_string;
  return "";
}

TWIN TWL_lookup(Window xwin){
  TWIN iter = listHead;
  while(iter && iter->my_window != xwin)
    iter = iter->my_next_node;
  return (iter ? iter : NULL_TEXT_WINDOW);
}

/*  [Last modified: 2007 06 28 at 19:33:35 GMT] */
